home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / bildschirmschoner / snowblank / source / xsnow / blank.c next >
C/C++ Source or Header  |  1996-04-07  |  13KB  |  505 lines

  1. /* --------------------------------------------------------------------
  2.  *
  3.  *             A christmas blanker inspired by xsnow
  4.  *
  5.  *     This is an advanced but slower version compared to snow
  6.  *
  7.  *    initialization/cleanup code copied from the dragon module
  8.  *      (dragon module: (C)Alexander Kneer and Michael D. Bayne)
  9.  * 
  10.  * -------------------------------------------------------------------- */
  11.  
  12.  
  13. #include <exec/memory.h>
  14. #include <math.h>
  15. #include <stdlib.h>
  16.  
  17. #include "/includes.h"
  18.  
  19. #define STAGES 2        /* Number of different shapes */
  20. #define BLANKDELAY 100        /* This many snowflakes are displayed before
  21.                  * we check if to continue blanking */
  22. #define COUNTLIMIT 6        /* max. number of moves in one direction */
  23. #define COUNTMIN 1        /* min. number of moves in one direction */
  24.  
  25. /* random generation function macros */
  26. #define COUNTFUNC RangeRand(COUNTLIMIT-COUNTMIN)+COUNTMIN
  27. #define DXFUNC    RangeRand(5)-2;
  28. #define DYFUNC    RangeRand(2)+1;
  29.  
  30. typedef enum { false, true, random } bool;
  31.  
  32. bool BIGFLAKES;
  33. int  NUMSNOW;
  34. bool COLLECT;
  35. bool SHOWSTARS;
  36. bool SHOWSNOWMEN;
  37. bool SHOWTREES;
  38. bool SHOWBG;
  39. int  NUMOBJ;
  40.  
  41.  
  42. int patx[10] = {  -1,-1, 1, 1, 0  , -1, 1, 0, 0, 0 };
  43. int paty[10] = {  -1, 1,-1, 1, 0  ,  0, 0, 1,-1, 0 };
  44.  
  45. int *collect;
  46. int *starx;
  47. int *stary;
  48. int starnum;
  49.  
  50. typedef struct 
  51.   { int x,y;            /* The current coordinates */
  52.     int dx,dy;            /* Movement direction is (dx,dy) */
  53.     int count;            /* How long to keep direction dx */
  54.     int stage;            /* STAGES different shapes */
  55.     short int mem[5];           /* stores the pixels below its shape */
  56.   } snowflake;
  57.  
  58.  
  59. /* Color pens */
  60. #define CBLACK 0
  61. #define CWHITE 1
  62. #define CGREEN 2
  63. #define CBROWN 3
  64. #define CDGREY 5
  65. #define CMGREY 6
  66. #define CLGREY 7
  67. #define CYELLOW 4
  68.  
  69.  
  70. Triplet *ColorTable = 0L;
  71.  
  72.  
  73. #define PR_FLAKE   0
  74. #define PR_BIG     2
  75. #define PR_COLLECT 3
  76. #define PR_STARS   5
  77. #define PR_BG      6
  78. #define PR_SNMAN   8
  79. #define PR_TREE    9
  80. #define PR_OBJ     11
  81. #define PR_MODE    13
  82.  
  83. VOID Defaults( PrefObject *Prefs )
  84. {
  85.   Prefs[PR_FLAKE].po_Level = 200;
  86.   Prefs[PR_BIG].po_Level = 1;
  87.   Prefs[PR_COLLECT].po_Level = 1;
  88.   Prefs[PR_STARS].po_Level = 1;
  89.   Prefs[PR_BG].po_Level = 1;
  90.   Prefs[PR_SNMAN].po_Level = 1;
  91.   Prefs[PR_OBJ].po_Level = 20;
  92.   Prefs[PR_TREE].po_Level = 1;
  93.   Prefs[PR_MODE].po_ModeID = getTopScreenMode();
  94. }
  95.  
  96.  
  97. /* Remove a single snowflake's image from the screen */
  98. __inline void undraw(snowflake *flake, struct RastPort *rp)
  99.   if (BIGFLAKES)
  100.     {
  101.       int *startx = patx + 5*(flake->stage);
  102.       int *starty = paty + 5*(flake->stage);
  103.       int i;
  104.       for (i=0; i<5; i++)
  105.     { if (flake->mem[i] != -1)
  106.             { SetAPen(rp,flake->mem[i]);
  107.               WritePixel(rp,flake->x+(*startx),flake->y+(*starty));
  108.             }
  109.          startx++;
  110.       starty++;
  111.     }
  112.     }
  113.   else
  114.     { if (flake->mem[0] != -1)
  115.         { SetAPen(rp,flake->mem[0]);
  116.           WritePixel(rp,flake->x,flake->y);
  117.         }
  118.     }
  119. }
  120.  
  121.  
  122. __inline void WriteLine(struct RastPort *rp, int width, int height, int x, int y, int scale, 
  123.                         int x1, int y1, int x2, int y2)
  124. { x1=x1*4*scale; y1=y1*4*scale; x2=x2*4*scale; y2=y2*4*scale;
  125.   /* all coordinates are now 1.000 times too big */
  126.   Move(rp,x+x1/1000,y+y1/1000);
  127.   Draw(rp,x+x2/1000,y+y2/1000);
  128. }
  129.  
  130.  
  131. void draw_tree(struct RastPort *rp, int width, int height)
  132. { int x,y;
  133.   int scale;
  134.   x = RangeRand(width-42);
  135.   y = RangeRand((height*3)/4-42)+height/4;
  136.   scale = (y*1000)/height;
  137.   SetAPen(rp,CBROWN);
  138.   WriteLine(rp,width,height,x,y,scale,4,10,6,10);
  139.   WriteLine(rp,width,height,x,y,scale,4,10,4,8);
  140.   WriteLine(rp,width,height,x,y,scale,6,10,6,8);
  141.   SetAPen(rp,CGREEN);
  142.   WriteLine(rp,width,height,x,y,scale,0,8,10,8);
  143.   WriteLine(rp,width,height,x,y,scale,0,8,3,6);
  144.   WriteLine(rp,width,height,x,y,scale,10,8,7,6);
  145.   WriteLine(rp,width,height,x,y,scale,3,6,1,6);
  146.   WriteLine(rp,width,height,x,y,scale,7,6,9,6);
  147.   WriteLine(rp,width,height,x,y,scale,1,6,3,4);
  148.   WriteLine(rp,width,height,x,y,scale,9,6,7,4);
  149.   WriteLine(rp,width,height,x,y,scale,3,4,2,4);
  150.   WriteLine(rp,width,height,x,y,scale,7,4,8,4);
  151.   WriteLine(rp,width,height,x,y,scale,2,4,4,2);
  152.   WriteLine(rp,width,height,x,y,scale,8,4,6,2);
  153.   WriteLine(rp,width,height,x,y,scale,4,2,3,2);
  154.   WriteLine(rp,width,height,x,y,scale,6,2,7,2);
  155.   WriteLine(rp,width,height,x,y,scale,3,2,5,0);
  156.   WriteLine(rp,width,height,x,y,scale,7,2,5,0);
  157. }
  158.  
  159.  
  160. __inline void WriteBall(struct RastPort *rp, int x, int y, int scale, 
  161.                         int x1, int y1, int r)
  162. { int i,j;
  163.   x1=x1*4*scale; y1=y1*4*scale; r=(r*4*scale)/1000;
  164.   /* all coordinates are now 1.000 times too big */
  165.   for (j=1; j<r; j++)
  166.     { i=r+1-j;
  167.       SetAPen(rp,16-((i*8)/r));
  168.       DrawEllipse(rp,x+x1/1000,y+y1/1000,i,i);
  169.     }
  170. }
  171.  
  172.  
  173. void draw_snowman(struct RastPort *rp, int width, int height)
  174. { int x,y;
  175.   int scale;
  176.   x = RangeRand(width-42);
  177.   y = RangeRand((height*3)/4-42)+height/4;
  178.   scale = (y*1000)/height;
  179.   SetAPen(rp,CLGREY);
  180.   /*if (scale > 400) WriteLine(rp,width,height,x,y,scale,1,4,7,4);*/
  181.   WriteBall(rp,x,y,scale,4,7,3);
  182.   WriteBall(rp,x,y,scale,4,4,2);
  183.   WriteBall(rp,x,y,scale,4,2,1);
  184. }
  185.  
  186.  
  187.  
  188. /* draw a winterly landscape with everything and more :) */
  189. LONG draw_landscape(struct Screen *scr, int width, int height, struct RastPort *rp)
  190. { int numobj,i;
  191.   LONG flg_end;
  192.  
  193.   /* first: the landscape */
  194.     { if (SHOWBG)
  195.         { int x,y;
  196.           int *hei = malloc(sizeof(int)*width);
  197.           hei[0]=0;
  198.           for (i=1; i<width; i++)
  199.             { hei[i] = hei[i-1]+RangeRand(3)-1;
  200.             }
  201.           for (y=height/4; y<height; y++)
  202.             { for (x=0; x<width; x++)
  203.                 { int val = ((y+hei[x]) * 100) / height;
  204.                   val = val - val/8 + RangeRand(val/4);
  205.                   if (val<0) val = 0;  
  206.                   val = (val * 8)/100;
  207.                   if (val<0) val = 0;
  208.                   if (val>7) val = 7;
  209.                   if (!val) SetAPen(rp,0); 
  210.                   else SetAPen(rp,val+8);
  211.                   WritePixel(rp,x,y);
  212.                 }
  213.               for (i=1; i<width; i++)
  214.                 { if (!RangeRand(3)) hei[i] = hei[i]+RangeRand(3)-1;
  215.                 }              
  216.           flg_end = ContinueBlanking();
  217.           ScreenToFront(scr);
  218.           if (flg_end != OK)
  219.                 { free(hei); return flg_end; }
  220.             }
  221.         }
  222.       /* else leave the background black */
  223.     }
  224.  
  225.   /* possibly stars */
  226.   if (SHOWSTARS)
  227.     { int count = RangeRand(50)+50;
  228.       int i;
  229.       starx = malloc(count*sizeof(int));
  230.       stary = malloc(count*sizeof(int));
  231.  
  232.       SetAPen(rp,CYELLOW);
  233.       for (i=0; i<count; i++)
  234.         { int x,y;
  235.           do { x = RangeRand(width);
  236.                y = RangeRand(height/4);
  237.              } while (ReadPixel(rp,x,y) != CBLACK);
  238.           WritePixel(rp,x,y);
  239.           starx[i] = x;
  240.           stary[i] = y;
  241.         } 
  242.       starnum = count;
  243.     }
  244.  
  245.   /* Draw some objects */
  246.   numobj = RangeRand(NUMOBJ/2)+NUMOBJ/2;
  247.   for (i=0; i<numobj; i++)
  248.     { switch(RangeRand(4))
  249.         { case 0: case 1: case 2: if (SHOWTREES)
  250.                                     draw_tree(rp,width,height); break;
  251.           case 3:                 if (SHOWSNOWMEN) 
  252.                                     draw_snowman(rp,width,height); break;
  253.         }
  254.     } 
  255.   return OK;
  256. }
  257.  
  258.  
  259. /* Draw a single snowflake's image to the screen */
  260. __inline void draw(snowflake *flake, struct RastPort *rp)
  261.   if (BIGFLAKES)
  262.     {
  263.       int *startx = patx + 5*(flake->stage);
  264.       int *starty = paty + 5*(flake->stage);
  265.       int i;
  266.       SetAPen(rp,1);
  267.       for (i=0; i<5; i++)
  268.     { int xx = flake->x+(*startx);
  269.           int yy = flake->y+(*starty);
  270.           flake->mem[i] = ReadPixel(rp,xx,yy);
  271.           if (flake->mem[i] == CWHITE)
  272.             { flake->mem[i] = -1;
  273.             }
  274.           else
  275.             WritePixel(rp,xx,yy);
  276.       startx++;
  277.       starty++;
  278.     }
  279.     }
  280.   else
  281.     { flake->mem[0] = ReadPixel(rp,flake->x,flake->y);
  282.       if (flake->mem[0] == CWHITE)
  283.         { flake->mem[0] = -1;
  284.         }
  285.       else
  286.         { SetAPen(rp,1);
  287.           WritePixel(rp,flake->x,flake->y);
  288.         }
  289.     }
  290. }
  291.  
  292.  
  293. /* change the position of a snowflake. If it leaves [0..width]x[0..height],
  294.  * generate a new one with coordinates (<random>,0) */
  295. __inline void update(snowflake *curr, int width, int height, struct RastPort *rp)
  296. { bool gen_new;
  297.   int oldx = curr->x;
  298.   if (curr->count > 0)
  299.     { curr->y = curr->y + curr->dy;
  300.       if (curr->y >= height-1)
  301.     { gen_new = true;
  302.     }
  303.       else
  304.     { curr->x = curr->x + curr->dx;
  305.       if (curr->x < 1 || curr->x >= width-1)
  306.         { gen_new = true;
  307.         }
  308.       else 
  309.         { gen_new = false;
  310.           (curr->count)--;
  311.           if (curr->count <= 0)
  312.         { curr->dx = DXFUNC;
  313.           curr->count = COUNTFUNC;
  314.         }
  315.           if (curr->stage)
  316.         { curr->stage--;
  317.         }
  318.           else
  319.         { curr->stage = STAGES-1;
  320.         }
  321.         }
  322.     }
  323.     }
  324.   
  325.   /* do we have to compute a new flake? */
  326.   if (gen_new)
  327.     { if (collect && curr->y > height-3)
  328.     { collect[oldx]--;
  329.       if (collect[oldx]<height-20)
  330.         { collect[oldx]=height-20;
  331.         }
  332.       
  333.       curr->x = oldx;
  334.       curr->y = collect[oldx];
  335.       draw(curr,rp);
  336.     }
  337.       curr->x = RangeRand(width-2)+1;
  338.       curr->y = 1;
  339.       curr->dx = DXFUNC;
  340.       curr->dy = DYFUNC;
  341.       curr->count = COUNTFUNC;
  342.       curr->stage = RangeRand(STAGES);
  343.     }
  344. }
  345.  
  346.  
  347.  
  348.  
  349. LONG snow(struct Screen *scr, SHORT width, SHORT height)
  350. {
  351.   unsigned int i;
  352.   LONG flg_end;
  353.   snowflake *flake,*curr;
  354.   int blankcount;
  355.   bool firstpass = true;
  356.   struct RastPort *rp = &(scr->RastPort);
  357.  
  358.   starx = NULL; stary = NULL;
  359.   /* first draw a winterly landscape */
  360.   flg_end = draw_landscape(scr,width,height,rp);
  361.   if (flg_end != OK)
  362.     { if (starx) free(starx);
  363.       if (stary) free(stary);
  364.       return flg_end;
  365.     }
  366.  
  367.   /* initialize the snow array */
  368.   flake = malloc(NUMSNOW*sizeof(snowflake));
  369.   curr = flake;
  370.   for (i=0; i<NUMSNOW; i++)
  371.     { curr->x = RangeRand(width-2)+1;
  372.       curr->y = RangeRand(height-2)+1;
  373.       curr->dx = DXFUNC;
  374.       curr->dy = DYFUNC;
  375.       curr->count = COUNTFUNC;
  376.       curr->stage = RangeRand(STAGES);
  377.       curr++;
  378.     }
  379.  
  380.   /* and the collect array */
  381.   if (COLLECT)
  382.     { collect = malloc(sizeof(int)*width);
  383.       for (i=0; i<width; i++)
  384.         { collect[i] = height-2;
  385.         }
  386.       collect[0] = 0;
  387.       collect[width-1] = 0;
  388.     }
  389.   else
  390.     { collect = NULL;
  391.     }
  392.  
  393.   /* Update all snowflakes forever. Update includes removal from the screen,
  394.    * computation of new position, drawing on the screen */
  395.   blankcount = BLANKDELAY;
  396.   while (1)
  397.     { curr = flake;
  398.       { if (SHOWSTARS)
  399.           { int num = RangeRand(starnum);
  400.             int x = starx[num];
  401.             int y = stary[num];
  402.             int val = ReadPixel(rp,x,y);
  403.             if (val != CWHITE)
  404.               { if (val == CYELLOW)
  405.                   { SetAPen(rp,CBLACK);
  406.                   }
  407.                 else
  408.                   { SetAPen(rp,CYELLOW);
  409.                   }
  410.                 WritePixel(rp,x,y);
  411.               }
  412.           }
  413.       }
  414.               
  415.       for (i=0; i<NUMSNOW; i++)
  416.     { /* Remove curr's image */
  417.       if (!firstpass) undraw(curr,rp);
  418.       /* compute new position and appearance */
  419.       update(curr,width,height,rp);
  420.       /* and display it */
  421.       draw(curr,rp);
  422.       /* can we continue? */
  423.       if (!blankcount)
  424.         { blankcount = BLANKDELAY;
  425.           flg_end = ContinueBlanking();
  426.           ScreenToFront(scr);
  427.           if (flg_end != OK)
  428.         { free(flake);
  429.            if (collect) free(collect);
  430.                   if (starx) free(starx);
  431.                   if (stary) free(stary);
  432.           return flg_end;
  433.         }
  434.         }
  435.       else
  436.         { blankcount--;
  437.         }
  438.       curr++;
  439.     }
  440.       if (firstpass) firstpass = false;
  441.     }
  442.   return OK;            /* just for the compiler */
  443. }
  444.  
  445.  
  446. bool val(bool x)
  447. { if (x==random)
  448.     return RangeRand(2);
  449.   else return x;
  450. }
  451.  
  452.  
  453. LONG Blank( PrefObject *Prefs )
  454. {
  455.     struct Screen *Scr;
  456.     struct Window *Wnd;
  457.     LONG RetVal;
  458.     
  459.         BIGFLAKES   = val(Prefs[PR_BIG].po_Level); 
  460.     NUMSNOW     = Prefs[PR_FLAKE].po_Level;
  461.     COLLECT     = val(Prefs[PR_COLLECT].po_Level);
  462.         SHOWSNOWMEN = val(Prefs[PR_SNMAN].po_Level);
  463.         SHOWSTARS   = val(Prefs[PR_STARS].po_Level);
  464.         SHOWTREES   = val(Prefs[PR_TREE].po_Level);
  465.         SHOWBG      = val(Prefs[PR_BG].po_Level);
  466.         NUMOBJ      = Prefs[PR_OBJ].po_Level;
  467.  
  468.     if( Scr = OpenScreenTags( NULL, SA_Depth, 4,
  469.                              SA_Quiet, TRUE, SA_DisplayID, Prefs[PR_MODE].po_ModeID,
  470.                              SA_Behind, TRUE, SA_Overscan, OSCAN_STANDARD,
  471.                              TAG_DONE ))
  472.     {
  473.         SetRGB4(&( Scr->ViewPort ), 0, 0, 0, 0 );
  474.         ColorTable = RainbowPalette( Scr, 0L, 1L, 0L );
  475.         SetRGB4(&( Scr->ViewPort ), 1, 15, 15, 15 ); /* white */
  476.                 SetRGB4(&( Scr->ViewPort ), 2,  0,  10, 0 ); /* green */
  477.                 SetRGB4(&( Scr->ViewPort ), 3,  8,  5,  4 ); /* brown */
  478.                 SetRGB4(&( Scr->ViewPort ), 4, 15, 15,  8 ); /* yellow */
  479.                 SetRGB4(&( Scr->ViewPort ), 5,  4,  4,  4 ); /* dark grey */
  480.                 SetRGB4(&( Scr->ViewPort ), 6,  8,  8,  8 ); /* mid grey */
  481.                 SetRGB4(&( Scr->ViewPort ), 7,  12,  12,  12 ); /* light grey */
  482.                 { int i;
  483.                   for (i=8; i<16; i++)
  484.                     {
  485.                       SetRGB4(&( Scr->ViewPort ), i,  i-7,  i-7,  i-7); /* different gray */
  486.                     } 
  487.                 }
  488.         Wnd = BlankMousePointer( Scr );
  489.         
  490.         do
  491.             RetVal = snow( Scr, Scr->Width, Scr->Height );
  492.         while( RetVal == OK );
  493.         
  494.         UnblankMousePointer( Wnd );
  495.         RainbowPalette( 0L, ColorTable, 1L, 0L );
  496.         CloseScreen( Scr );
  497.     }
  498.     else
  499.         RetVal = FAILED;
  500.     
  501.     return RetVal;
  502. }
  503.